home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / net / cslip_sana2.lha / slip / cslip.c < prev    next >
C/C++ Source or Header  |  1993-06-29  |  19KB  |  664 lines

  1. /*
  2.  *            COMPRESSED TCP HEADERS
  3.  *
  4.  * Reduce the 40 byte TCP header to as little as 5 or even 3 bytes
  5.  * (of which 2 bytes are the original TCP checksum).
  6.  *
  7.  * See RFC 1144 "Compression of TCP/IP Headers for Low-Speed Serial
  8.  * Links", V. Jacobson, February 1990, for the exciting details.
  9.  *
  10.  * The code in this file is derived from and very similar to the example
  11.  * implementation provided in RFC 1144, and is therefore sort-of covered
  12.  * by its copyright:
  13.  *
  14.  * Copyright (C) 1989 Regents of the University of California.
  15.  *
  16.  * This adaptation by Olaf 'Rhialto' Seibert.
  17.  * - fixed a number of sizeof(int) == 4 assumptions.
  18.  * - allow a few packets to be sent compressed before it is officially
  19.  *   enabled, so as to trigger the other side into compressed mode.
  20.  *
  21.  * Memory usage: < 3K of 68000 code, plus ~ 4K buffer space per line.
  22.  */
  23.  
  24. #include <string.h>
  25. #include "slip_device.h"
  26. #if DEBUG
  27. #include "syslog.h"
  28. #else
  29. #define debug(x)
  30. #endif
  31.  
  32. #define calloc(n,m)     AllocVec((n) * (m), MEMF_CLEAR)
  33. #define free(p)         FreeVec(p)
  34.  
  35. #ifndef EXEC_MEMORY_H
  36. #include <exec/memory.h>
  37. #endif
  38. #include <clib/exec_protos.h>
  39. #ifdef __SASC
  40. #include <pragmas/exec_pragmas.h>
  41. #endif
  42.  
  43. #define ihl(v_ihl)      lonibble(v_ihl) /* extract ip header length */
  44. #define tcp_offset(tcp)  ((u_char)(tcp)->offset >> DSHIFT)
  45.  
  46. /* Appendix A.2  Compression */
  47.  
  48. u_char
  49. sl_compress_tcp(m, comp)
  50. struct mbuf *m;
  51. struct slcompress *comp;
  52. {
  53.     register struct cstate *cs = comp->last_cs->cs_next;
  54.     register struct ip_header *ip = mtod(m, struct ip_header *);
  55.     register u_int hlen = ihl(ip->v_ihl);
  56.     register struct tcp_header *oth;    /* last TCP header */
  57.     register struct tcp_header *th;    /* current TCP header */
  58.     register u_long deltaS, deltaA;    /* general purpose temporaries */
  59.     register u_int changes = 0;     /* change mask */
  60.     u_char new_seq[16];         /* changes from last to current */
  61.     register u_char *cp = new_seq;
  62.  
  63.     debug((">sl_compress_tcp %lx %d\n", m->m_off, m->m_len));
  64.     /* Appendix B.2  Backwards compatible SLIP servers */
  65. #ifdef TRYCOUNT
  66.     if (comp->on == 0) {
  67.     debug(("<sl_compress_tcp: not on\n"));
  68.     return TYPE_IP;
  69.     }
  70. #else
  71.     if ((comp->flags & SLF_ON) == 0) {
  72.     debug(("<sl_compress_tcp: not on\n"));
  73.     return TYPE_IP;
  74.     }
  75. #endif
  76.  
  77.     if (ip->protocol != TCP_PTCL) {     /* Rhialto */
  78.     comp->sls_o_nontcp++;
  79.     debug(("<sl_compress_tcp: not tcp\n"));
  80.     return TYPE_IP;
  81.     }
  82.  
  83.     /*
  84.      * Bail if this is an IP fragment or if the TCP packet isn't
  85.      * `compressible' (i.e., ACK isn't set or some other control bit is
  86.      * set). (We assume that the caller has already made sure the packet
  87.      * is IP proto TCP).
  88.      */
  89.     if ((ip->fl_offs & htons(0x3fff)) || m->m_len < 40) {
  90.     comp->sls_o_tcp++;
  91.     debug(("<sl_compress_tcp: tcp frag\n"));
  92.     return TYPE_IP;
  93.     }
  94.  
  95.     th = (struct tcp_header *)&((int32 *) ip)[hlen];
  96.     if ((th->flags & (SYN | FIN | RST | ACK)) != ACK) {
  97.     comp->sls_o_tcp++;
  98.     debug(("<sl_compress_tcp: tcp flags\n"));
  99.     return TYPE_IP;
  100.     }
  101.  
  102.     /*
  103.      * Packet is compressible -- we're going to send either a
  104.      * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need to
  105.      * locate (or create) the connection state. Special case the most
  106.      * recently used connection since it's most likely to be used again &
  107.      * we don't have to do any reordering if it's used.
  108.      */
  109.     if (ip->source != cs->cs_ip.source ||
  110.     ip->dest != cs->cs_ip.dest ||
  111.     *(int32 *)th != cs->cs_hdr4[ihl(cs->cs_ip.v_ihl)]) {
  112.  
  113.     /*
  114.      * Wasn't the first -- search for it.
  115.      *
  116.      * States are kept in a circularly linked list with last_cs
  117.      * pointing to the end of the list. The list is kept in lru
  118.      * order by moving a state to the head of the list whenever
  119.      * it is referenced. Since the list is short and,
  120.      * empirically, the connection we want is almost always near
  121.      * the front, we locate states via linear search. If we don't
  122.      * find a state for the datagram, the oldest state is re-used.
  123.      */
  124.     register struct cstate *lcs;
  125.     register struct cstate *lastcs = comp->last_cs;
  126.  
  127.     do {
  128.         lcs = cs;
  129.         cs = cs->cs_next;
  130.         comp->sls_o_searches++;
  131.  
  132.         if (ip->source == cs->cs_ip.source &&
  133.         ip->dest == cs->cs_ip.dest &&
  134.         *(int32 *)th == cs->cs_hdr4[ihl(cs->cs_ip.v_ihl)])
  135.         goto found;
  136.     } while (cs != lastcs);
  137.  
  138.     /*
  139.      * Didn't find it -- re-use oldest cstate. Send an uncompressed
  140.      * packet that tells the other side what connection number
  141.      * we're using for this conversation. Note that since the
  142.      * state list is circular, the oldest state points to the newest
  143.      * and we only need to set last_cs to update the lru linkage.
  144.      */
  145.     comp->sls_o_misses++;
  146.     comp->last_cs = lcs;
  147.     hlen += tcp_offset(th); /* add tcp header length */
  148.     hlen *= sizeof(int32);
  149.  
  150.     goto uncompressed;
  151.  
  152.     found:
  153.     /* Found it -- move to the front on the connection list. */
  154.     if (lastcs == cs)
  155.         comp->last_cs = lcs;
  156.     else {
  157.         lcs->cs_next = cs->cs_next;
  158.         cs->cs_next = lastcs->cs_next;
  159.         lastcs->cs_next = cs;
  160.     }
  161.     }
  162.     debug((" sl_compress_tcp: found\n"));
  163. #ifdef TRYCOUNT
  164.     /*
  165.      * For found connections, try a few TCP_UNCOMPRESSED packets even if
  166.      * we're not SL_ON yet. (This doesn't happen on new connections;
  167.      * they will be TCP_UNCOMPRESSED regardless - FIXME.)
  168.      */
  169.     if (comp->on > 0) {
  170.     comp->on--;
  171.     debug((" sl_compress_tcp: trycount %d\n", comp->on));
  172.     goto uncompressed;
  173.     }
  174. #endif
  175.     /*
  176.      * Make sure that only what we expect to change changed. The 1st
  177.      * line of the 'if' checks the IP protocol version, header length &
  178.      * type of service. The 2nd line checks the "Don't fragment" bit.
  179.      * The 3rd line checks the time-to-live and protocol (the protocol
  180.      * check is unnecessary but costless). The 4th line checks the TCP
  181.      * header length. The 5th line checks IP options, if any. The 6th
  182.      * line checks TCP options, if any. If any of these things are
  183.      * different between the previous & current datagram, we send the
  184.      * current datagram "uncompressed".
  185.      */
  186.     oth = (struct tcp_header *) &cs->cs_hdr4[hlen];
  187.     deltaS = hlen;
  188.     hlen += tcp_offset(th);
  189.     hlen *= sizeof(int32);
  190.  
  191.     if (((u_short *) ip)[0] != ((u_short *) &cs->cs_ip)[0] || /* v_ihl,tos */
  192.     ((u_short *) ip)[3] != ((u_short *) &cs->cs_ip)[3] || /* fl_offs */
  193.     ((u_short *) ip)[4] != ((u_short *) &cs->cs_ip)[4] || /* ttl, protocol */
  194.     th->offset != oth->offset ||
  195.     (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) * sizeof(int32))) ||
  196.     (tcp_offset(th) > 5 && BCMP(th + 1, oth + 1, (tcp_offset(th) - 5) * sizeof(int32)))) {
  197.     debug((" sl_compress_tcp: header changed\n"));
  198.     goto uncompressed;
  199.     }
  200.  
  201.     /*
  202.      * Figure out which of the changing fields changed. The receiver
  203.      * expects changes in the order: urgent, window, ack, seq.
  204.      */
  205.     if (th->flags & URG) {
  206.     deltaS = ntohs(th->up);
  207.     ENCODEZ(deltaS);
  208.     changes |= NEW_U;
  209.     } else if (th->up != oth->up) {
  210.     /*
  211.      * argh! URG not set but urp changed -- a sensible
  212.      * implementation should never do this but RFC 793 doesn't
  213.      * prohibit the change so we have to deal with it.
  214.      */
  215.     debug((" sl_compress_tcp: up changed\n"));
  216.     goto uncompressed;
  217.     }
  218.  
  219.     if (deltaS = (u_short) (ntohs(th->wnd) - ntohs(oth->wnd))) {
  220.     ENCODE(deltaS);
  221.     changes |= NEW_W;
  222.     }
  223.     if (deltaA = ntohs(th->ack) - ntohs(oth->ack)) {
  224.     if (deltaA > 0xffff)
  225.         goto uncompressed;
  226.     ENCODE(deltaA);
  227.     changes |= NEW_A;
  228.     }
  229.     if (deltaS = ntohs(th->seq) - ntohs(oth->seq)) {
  230.     if (deltaS > 0xffff)
  231.         goto uncompressed;
  232.     ENCODE(deltaS);
  233.     changes |= NEW_S;
  234.     }
  235.     /*
  236.      * Look for the special-case encodings.
  237.      */
  238.     switch (changes) {
  239.  
  240.     case 0:
  241.     /*
  242.      * Nothing changed. If this packet contains data and the last
  243.      * one didn't, this is probably a data packet following an
  244.      * ack (normal on an interactive connection) and we send it
  245.      * compressed. Otherwise it's probably a retransmit,
  246.      * retransmitted ack or window probe. Send it uncompressed
  247.      * in case the other side missed the compressed version.
  248.      */
  249.     if (ip->length != cs->cs_ip.length &&
  250.         ntohs(cs->cs_ip.length) == hlen)
  251.         break;
  252.  
  253.     debug((" sl_compress_tcp: retransmission ->\n"));
  254.     /* fall through */
  255.  
  256.     case SPECIAL_I:
  257.     case SPECIAL_D:
  258.     /*
  259.      * Actual changes match one of our special case encodings --
  260.      * send the packet uncompressed.
  261.      */
  262.     debug((" sl_compress_tcp: changes match special\n"));
  263.     goto uncompressed;
  264.  
  265.     case NEW_S | NEW_A:
  266.     if (deltaS == deltaA &&
  267.         deltaS == ntohs(cs->cs_ip.length) - hlen) {
  268.         /* special case for echoed terminal traffic */
  269.         debug((" sl_compress_tcp: special interactive\n"));
  270.         changes = SPECIAL_I;
  271.         cp = new_seq;
  272.     }
  273.     break;
  274.  
  275.     case NEW_S:
  276.     if (deltaS == ntohs(cs->cs_ip.length) - hlen) {
  277.         /* special case for data xfer */
  278.         debug((" sl_compress_tcp: special data\n"));
  279.         changes = SPECIAL_D;
  280.         cp = new_seq;
  281.     }
  282.     break;
  283.     }
  284.     deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
  285.     if (deltaS != 1) {
  286.     ENCODEZ(deltaS);
  287.     changes |= NEW_I;
  288.     }
  289.     if (th->flags & PSH)
  290.     changes |= TCP_PUSH_BIT;
  291.     /*
  292.      * Grab the cksum before we overwrite it below. Then update our
  293.      * state with this packet's header.
  294.      */
  295.     deltaA = ntohs(th->checksum);
  296.     BCOPY(ip, &cs->cs_ip, hlen);
  297.  
  298.     /*
  299.      * We want to use the original packet as our compressed packet.
  300.      * (cp - new_seq) is the number of bytes we need for compressed
  301.      * sequence numbers. In addition we need 1 byte for the change
  302.      * mask, 1 for the connection id and 2 for the tcp checksum.
  303.      * So, (cp - new_seq) + 4 bytes of header are needed.
  304.      * hlen is how many bytes of the original packet we tossed so
  305.      * subtract the two to to get the packet size difference.
  306.      */
  307.  
  308.     deltaS = cp - new_seq;
  309.     cp = (u_char *)ip;
  310.     if (comp->last_xmit != cs->cs_id) {
  311.     comp->last_xmit = cs->cs_id;
  312.     hlen -= deltaS + 4;
  313.     cp += hlen;
  314.     *cp++ = changes | NEW_C;
  315.     *cp++ = cs->cs_id;
  316.     } else {
  317.     hlen -= deltaS + 3;
  318.     cp += hlen;
  319.     *cp++ = changes;
  320.     }
  321.     m->m_len -= hlen;
  322.     m->m_off += hlen;
  323.     *cp++ = deltaA >> 8;    /* checksum */
  324.     *cp++ = deltaA;
  325.     BCOPY(new_seq, cp, deltaS);
  326.  
  327.     comp->sls_o_compressed++;
  328.     debug(("<sl_compress_tcp: compressed\n"));
  329.     return TYPE_COMPRESSED_TCP;
  330.  
  331. uncompressed:
  332.     debug((" sl_compress_tcp: uncompressed\n"));
  333.     /*
  334.      * Update connection state cs & send uncompressed packet
  335.      * ('uncompressed' means a regular ip/tcp packet but with the
  336.      * 'conversation id' we hope to use on future compressed packets
  337.      * in the protocol field).
  338.      */
  339.     BCOPY(m->m_off, cs->cs_hdr, hlen);
  340.     ip->protocol = cs->cs_id;
  341.     comp->last_xmit = cs->cs_id;
  342.  
  343.     comp->sls_o_uncompressed++;
  344.     debug(("<sl_compress_tcp: uncompressed\n"));
  345.     return TYPE_UNCOMPRESSED_TCP;
  346. }
  347.  
  348. /* OIS:
  349.  * This function should be called if the most recently compressed packet
  350.  * may have been lost on its way to the next gateway. It forces the next
  351.  * packet on the same connection to be uncompressed, in an attempt to
  352.  * minimise the effect of the dropped packet. The method used is to change
  353.  * one of the 'unchanging' header fields in the saved header, so that none
  354.  * of the other saved headers will be dropped.
  355.  */
  356. void
  357. sl_xmit_error(comp)
  358. struct slcompress *comp;
  359. {
  360.     if (comp->last_xmit < MAX_STATES) {
  361.     comp->tstate[comp->last_xmit].cs_ip.v_ihl--;
  362.     }
  363. }
  364.  
  365. /* Appendix A.3  Decompression */
  366.  
  367. struct mbuf *
  368. sl_uncompress_tcp(m, type, comp)
  369. struct mbuf *m;
  370. u_int type;
  371. struct slcompress *comp;
  372. {
  373.     register char *bufp;
  374.     register u_char *cp;
  375.     register u_int hlen, changes;
  376.     register struct tcp_header *th;
  377.     register struct cstate *cs;
  378.     register struct ip_header *ip;
  379.     int len;
  380.  
  381.     debug((">sl_uncompress_tcp\n"));
  382.  
  383.     switch (type) {
  384.     case TYPE_ERROR:
  385.     default:
  386.     debug((" sl_uncompress_tcp: ERROR\n"));
  387.     goto bad;
  388.     case TYPE_IP:
  389.     debug((" sl_uncompress_tcp: IP\n"));
  390.     comp->sls_i_ip++;
  391. #ifdef SLF_MAYBE
  392.     /*
  393.      * If we receive TYPE_IP packets, investigate if they could have
  394.      * been sent compressed. If so, the other side probably doesn't
  395.      * understand compressed packets. This test is identical to those
  396.      * in sl_compress_tcp().
  397.      * (OIS)
  398.      */
  399.     bufp = m->m_off;
  400.     ip = (struct ip_header *)bufp;
  401.     if (comp->flags & SLF_MAYBE &&
  402.         ip->protocol == TCP_PTCL &&
  403.         (ip->fl_offs & htons(0x3fff)) == 0 &&
  404.         (th = (struct tcp_header *)
  405.          offset(m, ihl(ip->v_ihl) * sizeof(int32), sizeof(*th))) &&
  406.         (th->flags & (SYN | FIN | RST | ACK)) == ACK) {
  407.         comp->flags &= ~(SLF_ON | SLF_MAYBE) ;
  408.         /* printf("Compression turned OFF\n"); */
  409.     }
  410. #endif
  411.     return m;
  412.     case TYPE_UNCOMPRESSED_TCP:
  413.     debug((" sl_uncompress_tcp: UNCOMPRESSED TCP\n"));
  414.     comp->sls_i_uncompressed++;
  415.     /* Appendix B.2  Backwards compatible SLIP servers */
  416.     if ((comp->flags & SLF_ALLOWED) == 0)
  417.         goto bad;
  418. #ifdef TRYCOUNT
  419.     comp->on = SL_ON;
  420. #else
  421.     comp->flags |= SLF_ON;
  422. #endif
  423.     /*
  424.      * Locate the saved state for this connection. If the state index
  425.      * is legal, clear the 'discard' flag.
  426.      */
  427.     bufp = m->m_off;
  428.     ip = (struct ip_header *)bufp;
  429.     if (ip->protocol > comp->rslot_limit)
  430.         goto bad;
  431.  
  432.     cs = &comp->rstate[comp->last_recv = ip->protocol];
  433.     comp->flags &= ~SLF_TOSS;
  434.     /*
  435.      * Restore the IP protocol field then save a copy of this
  436.      * packet header. (The checksum is zeroed in the copy so we
  437.      * don't have to zero it each time we process a compressed
  438.      * packet.)
  439.      */
  440.     ip->protocol = TCP_PTCL;
  441.     hlen = ihl(ip->v_ihl);
  442.     hlen += tcp_offset((struct tcp_header *) & ((int32 *)ip)[hlen]);
  443.     hlen *= sizeof(int32);
  444.     BCOPY(ip, cs->cs_hdr, hlen);
  445.     cs->cs_ip.checksum = 0;
  446.     cs->cs_hlen = hlen;
  447.  
  448.     return m;
  449.  
  450.     case TYPE_COMPRESSED_TCP:
  451.     debug((" sl_uncompress_tcp: COMPRESSED TCP\n"));
  452.     comp->sls_i_compressed++;
  453.     /* Appendix B.2  Backwards compatible SLIP servers */
  454.     if ((comp->flags & SLF_ALLOWED) == 0)
  455.         goto bad;
  456.     break;
  457.     }
  458.  
  459.     /* We've got a compressed packet. */
  460.     bufp = m->m_off;
  461.     cp = bufp;
  462.     changes = *cp++;
  463.     if (changes & NEW_C) {
  464.     /*
  465.      * Make sure the state index is in range, then grab the
  466.      * state. If we have a good state index, clear the 'discard'
  467.      * flag.
  468.      */
  469.     if (*cp > comp->rslot_limit)
  470.         goto bad;
  471.  
  472.     comp->flags &= ~SLF_TOSS;
  473.     comp->last_recv = *cp++;
  474.     } else {
  475.     /*
  476.      * This packet has an implicit state index. If we've had a
  477.      * line error since the last time we got an explicit state
  478.      * index, we have to toss the packet.
  479.      */
  480.     if (comp->flags & SLF_TOSS) {
  481.         comp->sls_i_tossed++;
  482.         debug(("<sl_uncompress_tcp: tossed\n"));
  483.         return NULL;
  484.     }
  485.     }
  486.  
  487.     /*
  488.      * Find the state then fill in the TCP checksum and PUSH bit.
  489.      */
  490.     cs = &comp->rstate[comp->last_recv];
  491.     hlen = ihl(cs->cs_ip.v_ihl) * sizeof(int32);
  492.     th = (struct tcp_header *) &((u_char *) &cs->cs_ip)[hlen];
  493.     th->checksum = htons((*cp << 8) | cp[1]);
  494.     cp += 2;
  495.     if (changes & TCP_PUSH_BIT)
  496.     th->flags |= PSH;
  497.     else
  498.     th->flags &= ~PSH;
  499.  
  500.     /*
  501.      * Fix up the state's ack, seq, urg and win fields based on the
  502.      * changemask.
  503.      */
  504.     switch (changes & SPECIALS_MASK) {
  505.     case SPECIAL_I:
  506.     {
  507.         register u_int i = ntohs(cs->cs_ip.length) - cs->cs_hlen;
  508.         debug((" sl_uncompress_tcp: special interactive\n"));
  509.  
  510.         th->ack = htonl(ntohl(th->ack) + i);
  511.         th->seq = htonl(ntohl(th->seq) + i);
  512.     }
  513.     break;
  514.     case SPECIAL_D:
  515.         debug((" sl_uncompress_tcp: special data\n"));
  516.     th->seq = htonl(ntohl(th->seq) + ntohs(cs->cs_ip.length)
  517.             - cs->cs_hlen);
  518.     break;
  519.     default:
  520.     debug((" sl_uncompress_tcp: other changemask\n"));
  521.     if (changes & NEW_U) {
  522.         th->flags |= URG;
  523.         DECODEU(th->up);
  524.     } else
  525.         th->flags &= ~URG;
  526.     if (changes & NEW_W)
  527.         DECODES(th->wnd);
  528.     if (changes & NEW_A)
  529.         DECODEL(th->ack);
  530.     if (changes & NEW_S)
  531.         DECODEL(th->seq);
  532.     }
  533.  
  534.     /* Update the new IP ID */
  535.     if (changes & NEW_I)
  536.     DECODES(cs->cs_ip.id)
  537.     else
  538.     cs->cs_ip.id = htons(ntohs(cs->cs_ip.id) + 1);
  539.  
  540.     /*
  541.      * At this point we have done the whole header.
  542.      * cp points to the first byte of data in the packet. We skip the
  543.      * 4-byte alignment here as SANA will copy it to the user anyway.
  544.      * Back up cp by the TCP/IP header length to make room for the
  545.      * reconstructed header (we assume the packet we were handed has
  546.      * enough space to prepend 128 bytes of header). Adjust the length
  547.      * to account for the new header & fill in the IP total length.
  548.      *
  549.      */
  550.     len = m->m_len;
  551.     len -= (cp - bufp);
  552.     if (len < 0)
  553.     /*
  554.      * We must have dropped some characters (crc should detect this
  555.      * but the slip framing won't)
  556.      */
  557.     goto bad;
  558.  
  559. #if 0
  560.     if ((int32)cp & 3) {
  561.     if (len > 0)
  562.         OVBCOPY(cp, (int32)cp & ~3, len);
  563.     cp = (u_char *) ((int32)cp & ~3);
  564.     }
  565. #endif
  566.  
  567.     m->m_off = cp -= cs->cs_hlen;
  568.     m->m_len = len += cs->cs_hlen;
  569.     cs->cs_ip.length = htons(len);
  570.     debug((" sl_uncompress_tcp: copy long header into packet\n"));
  571.     BCOPY(&cs->cs_ip, cp, cs->cs_hlen);
  572.  
  573.     /* recompute the ip header checksum */
  574.     {
  575.     /*register u_short *bp = (u_short *)cp;*/
  576.     register u_short *bp = (u_short *)&cs->cs_ip;
  577.  
  578.     for (changes = 0; hlen > 0; hlen -= 2)
  579.         changes += ntohs(*bp++);
  580.     changes = (changes & 0xffff) + (changes >> 16);
  581.     changes = (changes & 0xffff) + (changes >> 16);
  582.     changes = htons(~changes);
  583.     bp = &((struct ip_header *)cp)->checksum;
  584.     ((u_char *)bp)[0] = changes >> 8;
  585.     ((u_char *)bp)[1] = changes;
  586.     }
  587.  
  588.     debug(("<sl_uncompress_tcp: done\n"));
  589.     return m;
  590.  
  591. bad:
  592.     comp->sls_i_error++;
  593.     comp->flags |= SLF_TOSS;
  594.  
  595.     debug(("<sl_uncompress_tcp: bad packet\n"));
  596.     return NULL;
  597. }
  598.  
  599. /* Appendix A.4  Initialisation */
  600.  
  601. void
  602. sl_compress_init(comp, rslots, tslots)
  603. struct slcompress *comp;
  604. int rslots;
  605. int tslots;
  606. {
  607.     register u_int i;
  608.     register struct cstate *tstate = NULL;
  609.  
  610.     /*
  611.      * Clean out any junk left from the last time the line was used.
  612.      */
  613.     memset(comp, 0, sizeof(*comp));
  614.     if ( rslots > 0  &&  rslots < 256 ) {
  615.     comp->rstate = calloc( rslots, sizeof(struct cstate) );
  616.     comp->rslot_limit = rslots - 1;
  617.     }
  618.  
  619.     if ( tslots > 0  &&  tslots < 256 ) {
  620.     tstate = calloc( tslots, sizeof(struct cstate) );
  621.     comp->tstate = tstate;
  622.     comp->tslot_limit = tslots - 1;
  623.     }
  624.     /*
  625.      * Link the transmit states into a circular list.
  626.      */
  627.     if (tstate > 0) {
  628.     for (i = comp->tslot_limit; i > 0; --i) {
  629.         tstate[i].cs_id = i;
  630.         tstate[i].cs_next = &tstate[i - 1];
  631.     }
  632.     tstate[0].cs_id = 0;
  633.     tstate[0].cs_next = &tstate[comp->tslot_limit];
  634.     comp->last_cs = &tstate[0];
  635.     }
  636.     /*
  637.      * Make sure we don't accidentally do CID compression
  638.      * (assumes MAX_STATES < 255).
  639.      */
  640.     comp->last_recv = NO_CID;
  641.     comp->last_xmit = NO_CID;
  642.     /*
  643.      * Set proper flags
  644.      */
  645.     comp->flags = SLF_TOSS | SLF_ALLOWED;
  646. #ifdef TRYCOUNT
  647.     if (tslots > 0)
  648.     comp->on = TRYCOUNT;
  649. #else
  650.     if (tslots > 0)
  651.     comp->flags |= SLF_ON;
  652. #endif
  653. }
  654.  
  655. void
  656. sl_compress_deinit(comp)
  657. struct slcompress *comp;
  658. {
  659.     if (comp->rstate)
  660.     free(comp->rstate);
  661.     if (comp->tstate)
  662.     free(comp->tstate);
  663. }
  664.